#ifndef UTILS_H
#define UTILS_H

#endif // UTILS_H

#pragma once
#include <iostream>
#include<fstream>
#include<string>
#include<vector>
#include<iterator>
#include<algorithm>
#include<tuple>
#include<time.h>
#include"rectangle.h"
#include"polygon.h"
#include"compose.h"
#include <regex>
#include "data.h"
using namespace std;
string name ;
string output_filename;

void write_vec(vector<float> v)
{
    ofstream output( "E://EDAdata//output2.csv", ios::out );
    if( ! output )
    {
        cerr << "Open output file error!" << endl;
        exit( -1 );
    }
    for( int i = 0; i < v.size(); i++ )
    {
        output << v[i]<<",";
    }
}

vector<string> Read(int&help)
{
    ifstream ifs;
    ifs.open(name, ios::in);
    if (!ifs.is_open())
    {
        cout << "open file error" << endl;
    }
    string buf;
    vector<string> s;

    while (getline(ifs, buf))
    {
        s.push_back(buf);
        //str[data_num] =buf;
        help++;
    }
    return s;
}
vector<string> filter(vector<string>s,vector<string>&s2)
{
    //string *s1=nullptr;
    int flag=0;
    int i1;

    for ( i1=0; i1<s.size(); i1++)
    {
         string s3="";
        for (int i2 = 0; i2 < s[i1].length(); i2++)
        {
            int index = 0;
            if (s[i1][i2] == '.')
            {
                flag = 1;
            }
            else if (s[i1][i2] == ','|| s[i1][i2] == '('||s[i1][i2] == ')')
            {
                flag = 0;
            }
            if(flag==0)
            {
                s3.append(1,s[i1][i2]);
            }


        }

        s2.push_back(s3);
    }
    return s2;
}

void String_to_data(vector<string> s, vector<int>& v, vector<int>& c, int& help)
{
    int tmp = 0;
    int value = 0;
    int count = 0;
    for (int j = 1; j < help; j += 2)
    {
        for (int j2 = 0; j2 < (s[j]).length(); j2++)
        {
            if ((s[j])[j2] != 44 && (s[j])[j2] != 40 && (s[j])[j2] != 41)
            {
                ++tmp;
            }
            else
            {
                switch (tmp) {
                case 1:
                    value = (s[j])[j2 - 1] - 48;
                    v.push_back(value);
                    tmp = 0; ++count;
                    break;
                case 2:
                    value = ((s[j])[j2 - 2] - 48) * 10 + (s[j])[j2 - 1] - 48;
                    v.push_back(value);
                    tmp = 0; ++count;
                    break;
                case 3:
                    value = ((s[j])[j2 - 3] - 48) * 100 + ((s[j])[j2 - 2] - 48) * 10 + ((s[j])[j2 - 1] - 48);
                    v.push_back(value);
                    tmp = 0; ++count;
                    break;
                default:
                    break;
                }
            }
        }
        c.push_back(count);
        count = 0;
    }


}
void GetZuobiao(int& x1, int& y1, int& x2, int& y2, vector<int>& x, vector<int>& y)
{
    sort(x.begin(), x.end());
    sort(y.begin(), y.end());
    x1 = x[0]; y1 = y[0];
    x2 = x[3]; y2 = y[3];
}
void Getmodel(vector<rectangle>& R, vector<int> v, vector<int> c, vector<polygon>& P, polygon(&PG)[1500])
{
    int jishu = 0;
    int PGjishu = 0;
    int rx1, ry1, rx2, ry2;//矩形左下角横纵坐标和右上角横纵坐标,r代表rectangle
    vector<int> x;//存横坐标
    vector<int> y;//存纵坐标

    for (auto i : c)
    {
        switch (i)
        {
        case 8:
            for (int a = jishu; a < jishu + 8; a++)
            {
                if (a % 2 == 0)
                {
                    x.push_back(v[a]);
                }
                else
                {
                    y.push_back(v[a]);
                }
            }
            GetZuobiao(rx1, ry1, rx2, ry2, x, y);
            x.clear();
            y.clear();
            R.push_back(rectangle(rx1, ry1, rx2, ry2));
            jishu += 8;
            break;
        case 12:
            for (int a1 = jishu; a1 < jishu + 12; a1++)
            {
                if (a1 % 2 == 0)
                {
                    x.push_back(v[a1]);
                }
                else
                {
                    y.push_back(v[a1]);
                }
            }
            for (int j = 0; j < 6; j++)
            {
                PG[PGjishu].allVertrx.push_back(pos(x[j], y[j]));
            }
            P.push_back(PG[PGjishu]);
            x.clear();
            y.clear();
            PGjishu++;
            jishu += 12;
            break;
        case 16:
            for (int a2 = jishu; a2 < jishu + 16; a2++)
            {
                if (a2 % 2 == 0)
                {
                    x.push_back(v[a2]);
                }
                else
                {
                    y.push_back(v[a2]);
                }
            }
            for (int j1 = 0; j1 < 8; j1++)
            {
                PG[PGjishu].allVertrx.push_back(pos(x[j1], y[j1]));
            }
            P.push_back(PG[PGjishu]);
            //p1 = NULL;
            x.clear();
            y.clear();
            PGjishu++;
            jishu += 16;
            break;
        default:
            break;
        }
    }
}
void AddTurn(vector<rectangle*> &R/*, vector<rectangle*> R2*/)
{
    int k = R.size();
    for (int i1 = 0; i1 < k; i1++)
    {
        rectangle* temp = R[i1]->get_copy();

        temp->delayConstru((*R[i1]).x1 + (*R[i1]).width, (*R[i1]).y1, (*R[i1]).x2 + (*R[i1]).height, (*R[i1]).y2 + (*R[i1]).width - (*R[i1]).height);
        R.push_back(temp);

    }

}

void print_map(int size)
{
    cout << "*******************表一*****************" << endl;
    /*for (int j = 0; j < size; j++)
        cout << j << " ";
    cout << endl;*/
    for (int i = 0; i < size; i++)
    {
        for (int j = 0; j < size; j++)
            cout << (peromone_map[i][j]) << " ";
        cout << endl;
        //cout << i + 1<<" ";

    }
    cout << "*******************表二*****************" << endl;
    for (int i = 0; i < size; i++)
    {
        for (int j = 0; j < size; j++)
            cout << (peromone_map2[i][j]) << " ";
        cout << endl;
    }
    /*cout << "*******************表二*****************" << endl;
    for (int i = 0; i < size; i++)
    {
        for (int j = 0; j < size; j++)
            cout << (peromone_map3[i][j]) << " ";
        cout << endl;
    }*/
}
int get_area_sum(const vector<rectangle*>& rec_temp) {
    int x2_max = 0;
    int y2_max = 0;
    for (int i = 0; i < rec_temp.size(); ++i) {
        if (x2_max < rec_temp[i]->x2) {
            x2_max = rec_temp[i]->x2;
        }

        if (y2_max < rec_temp[i]->y2) {
            y2_max = rec_temp[i]->y2;
        }
    }
    //cout << "width:" << x2_max<<endl;
    //cout << "height" << y2_max << endl;
    return x2_max * y2_max;
}

int get_selected_prob_id(vector<double> prob_table) {
    for (int i = 1; i < prob_table.size(); ++i) {
        prob_table[i] = prob_table[i - 1] + prob_table[i];
    }
    static int i = 0;

    srand((unsigned int)(time(NULL) + i));
    i += 378;
    int random_int = (rand() % 100) + 1;
    for (int i = 0; i < prob_table.size(); i++) {
        if (i == 0) {
            if (random_int <= prob_table[i] * 100) {
                return i;
            }
        }
        else if (i == prob_table.size() - 1) {
            return i;
        }
        else {
            if (((prob_table[i - 1] * 100) < random_int) && (random_int <= (prob_table[i] * 100))) {
                return i;
            }
        }
    }
}
double add_prob(const rectangle& rec, const vector<rectangle*>& rt_q) {
    for (int i = 0; i < rt_q.size(); ++i) {
        if (rt_q[i]->x2 > rec.x2&&rt_q[i]->y2 > rec.y2) {
            return 3.5;
        }
    }
    return 0;
}
int select_by_probability(const vector<rectangle*>& rt_q) {
    vector<double> prob_table;
    double sum=0;
    for (int i = 0; i < rt_q.size(); ++i) {
        double temp = add_prob(*rt_q[i], rt_q)+pow((((double)min(rt_q[i]->x2,rt_q[i]->y2)/max(rt_q[i]->x2, rt_q[i]->y2))),1);
        prob_table.push_back(temp);
        sum += temp;
    }
    for (int i = 0; i < rt_q.size(); ++i) {
        prob_table[i] = prob_table[i] / sum;
    }
    return get_selected_prob_id(prob_table);
}

float combination_utilization_rate(const rectangle* r1, const rectangle* r2)
{
    float area1;
    float area2 = r1->area + r2->area;
    float x_max;
    float y_max;
    float x_min;
    float y_min;
    float rate;//组合面积利用率
    if (r1->x2 > r2->x2)
        x_max = r1->x2;
    else
        x_max = r2->x2;
    if (r1->y2 > r2->y2)
        y_max = r1->y2;
    else
        y_max = r2->y2;

    //找左下点
    if (r1->x1 < r2->x1)
        x_min = r1->x1;
    else
        x_min = r2->x1;
    if (r1->y1 < r2->y1)
        y_min = r1->y1;
    else
        y_min = r2->y1;
    area1 = (x_max - x_min)*(y_max - y_min);
    rate = area2 / area1;
    return rate;
}

void combination_update_map(const vector<rectangle*>& rt_q)
{
    vector<rectangle*> temp = rt_q;
    for (int i = 0; i < temp.size(); i++)
    {
        for (int j =0; j < temp.size(); j++)
        {
            if (i > j)
            {
                temp[j]->set_up(temp[i]);
                float rate = combination_utilization_rate(temp[i], temp[j]);
                peromone_map3[i][j] = rate;
            }

            if (i < j)
            {
                temp[j]->set_right(temp[i]);
                float rate = combination_utilization_rate(temp[i], temp[j]);
                peromone_map3[i][j] = rate;
            }
        }
    }
    print_map(temp.size());
}

string resolution_path(const string& name) {

    string r;
    for (int i = 0; i < name.length(); i++)
    {
        if (name[i] >= '0'&&name[i] <= '9')
        {
            r += name[i];
        }
    }
    return "/home/eda20346/project/verify_results/result_" + r + ".txt";

}

bool judge_if_concave(const polygon& poly){
    if(poly.allVertrx.size()==6){
        return false;
    }
    vector<pos> top_pos;
    vector<pos> low_pos;
    int choice=0;
    for(int i=1;i<=4;i++){
        for(const pos& temp_pos:poly.allVertrx){
            for(const pos& check_pos:poly.allVertrx){
                if(i==1){
                    if(temp_pos.x==check_pos.x&&temp_pos.y<check_pos.y){
                        top_pos.push_back(temp_pos);
                        low_pos.push_back(check_pos);//凹口向下
                    }
                }
                else if(i==2){
                    if(temp_pos.x==check_pos.x&&temp_pos.y>check_pos.y){
                        top_pos.push_back(temp_pos);
                        low_pos.push_back(check_pos);//凹口向上
                    }
                }
                else if(i==3){
                    if(temp_pos.y==check_pos.y&&temp_pos.x>check_pos.x){
                        top_pos.push_back(temp_pos);
                        low_pos.push_back(check_pos);//凹口向右面
                    }
                }
                else{
                    if(temp_pos.y==check_pos.y&&temp_pos.x<check_pos.x){
                        top_pos.push_back(temp_pos);
                        low_pos.push_back(check_pos);//凹口向左面
                    }
                }
            }
        }
        if(top_pos.size()==4&&low_pos.size()==4){
            choice=i;
            break;
        }
        else{
            top_pos.clear();
            low_pos.clear();
        }
    }
    if(top_pos.size()==0&&low_pos.size()==0){
        return false;
    }
    vector<int> xy_top_rec;
    vector<int> xy_low_rec;
    if(choice==2||choice==3){
        if(choice==2){
            for(const pos& temp:top_pos){
                xy_top_rec.push_back(temp.y);
            }
            for(const pos& temp:low_pos){
                xy_low_rec.push_back(temp.y);
            }
        }
        else{
            for(const pos& temp:top_pos){
                xy_top_rec.push_back(temp.x);
            }
            for(const pos& temp:low_pos){
                xy_low_rec.push_back(temp.x);
            }
        }
        if(*min_element(xy_top_rec.begin(),xy_top_rec.end())>*max_element(xy_low_rec.begin(),xy_low_rec.end())){
            return true;
        }
    }
    if(choice==1||choice==4){
        if(choice==1){
            for(const pos& temp:top_pos){
                xy_top_rec.push_back(temp.y);
            }
            for(const pos& temp:low_pos){
                xy_low_rec.push_back(temp.y);
            }
        }
        else{
            for(const pos& temp:top_pos){
                xy_top_rec.push_back(temp.x);
            }
            for(const pos& temp:low_pos){
                xy_low_rec.push_back(temp.x);
            }
        }
        if(*max_element(xy_top_rec.begin(),xy_top_rec.end())<*min_element(xy_low_rec.begin(),xy_low_rec.end())){
            return true;
        }

    }
    return false;
}

